/*
 * COPYRIGHT:	2010 Christopher Smith, licenced under the GNU GPL v2; see COPYING in the top level directory
 * PROJECT:		sdedit
 * FILE:		ntapi.cpp
 * PURPOSE:		undocumented (for user-mode at least) NT level structures and functions
 *				
 */

#define NTSYSAPI DECLSPEC_IMPORT

//typedef ULONG NTSTATUS;
//typedef NTSTATUS *PNTSTATUS;

BOOLEAN FORCEINLINE NT_SUCCESS(NTSTATUS Status)
{
	return Status >= 0;
}

BOOLEAN FORCEINLINE NT_FAILURE(NTSTATUS Status)
{
	return Status < 0;
}

BOOLEAN FORCEINLINE NT_STRICT_SUCCESS(NTSTATUS Status)
{
	return (ULONG)Status >> 30 == 0;
}

BOOLEAN FORCEINLINE NT_INFORMATION(NTSTATUS Status)
{
	return (ULONG)Status >> 30 == 1;
}

BOOLEAN FORCEINLINE NT_WARNING(NTSTATUS Status)
{
	return (ULONG)Status >> 30 == 2;
}

BOOLEAN FORCEINLINE NT_ERROR(NTSTATUS Status)
{
	return (ULONG)Status >> 30 == 3;
}

struct IO_STATUS_BLOCK
{
    union
	{
        NTSTATUS Status;
        PVOID Pointer;
    };
    ULONG_PTR Information;
};

struct UNICODE_STRING
{
	USHORT Length;
	USHORT MaximumLength;
	WCHAR *Buffer;
};

typedef UNICODE_STRING *PUNICODE_STRING;

struct ANSI_STRING
{
	USHORT Length;
	USHORT MaximumLength;
	CHAR *Buffer;
};

typedef ANSI_STRING *PANSI_STRING;

typedef ANSI_STRING STRING;
typedef PANSI_STRING PSTRING;

struct OBJECT_ATTRIBUTES
{
	ULONG Length;
	HANDLE RootDirectory;
	UNICODE_STRING *ObjectName;
	ULONG Attributes;
	SECURITY_DESCRIPTOR *SecurityDescriptor;
	SECURITY_QUALITY_OF_SERVICE *SecurityQualityOfService;
};

const ULONG ObjectBasicInformation =	0;
const ULONG ObjectNameInformation =	1;

typedef ULONG OBJECT_INFORMATION_CLASS;

struct OBJECT_BASIC_INFORMATION
{
	ULONG Attributes;
	ACCESS_MASK GrantedAccess;
	ULONG HandleCount;
	ULONG PointerCount;
	ULONG PagedPoolUsage;
	ULONG NonPagedPoolUsage;
	ULONG Reserved[3];
	ULONG NameInformationLength;
	ULONG TypeInformationLength;
	ULONG SecurityDescriptorLength;
	LARGE_INTEGER CreateTime;
};

typedef ULONG FILE_INFORMATION_CLASS;

static ULONG const FileDirectoryInformation =		1;
static ULONG const FileBasicInformation =			4;
static ULONG const FileNameInformation =			9;
static ULONG const FileAlternateNameInformation =	21;

struct FILE_DIRECTORY_INFORMATION
{
	ULONG NextEntryOffset;
	ULONG Reserved;
	LARGE_INTEGER CreationTime;
	LARGE_INTEGER LastAccessTime;
	LARGE_INTEGER LastWriteTime;
	LARGE_INTEGER ChangeTime;
	LARGE_INTEGER EndOfFile;
	LARGE_INTEGER AllocationSize;
	ULONG FileAttributes;
	ULONG FileNameLength;
	WCHAR FileName[ANYSIZE_ARRAY];
};

struct FILE_BASIC_INFORMATION
{
	LARGE_INTEGER CreationTime;
	LARGE_INTEGER LastAccessTime;
	LARGE_INTEGER LastWriteTime;
	LARGE_INTEGER ChangeTime;
	ULONG FileAttributes;
};

struct FILE_NAME_INFORMATION
{
	ULONG FileNameLength;
	WCHAR FileName[ANYSIZE_ARRAY];
};


static ULONG const FILE_DIRECTORY_FILE =			0x00000001;
static ULONG const FILE_SYNCHRONOUS_IO_ALERT =		0x00000010;
static ULONG const FILE_SYNCHRONOUS_IO_NONALERT =	0x00000020;
static ULONG const FILE_NON_DIRECTORY_FILE =		0x00000040;
//static ULONG const FILE_OPEN_FOR_RECOVERY =			0x00000400;
static ULONG const FILE_OPEN_FOR_BACKUP_INTENT =	0x00004000;
static ULONG const OBJ_CASE_INSENSITIVE =			0x00000040;
static ULONG const OBJ_OPENIF =						0x00000080;

struct KEY_BASIC_INFORMATION
{
	LARGE_INTEGER LastWriteTime;
	ULONG TitleIndex;
	ULONG NameLength;
	WCHAR Name[ANYSIZE_ARRAY];
};

static ULONG const KeyBasicInformation = 0;

struct CLIENT_ID
{
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
};

//enum TOKEN_INFORMATION_CLASS
//{
//	TokenUser = 1,
//	TokenGroups,
//	TokenPrivileges,
//	TokenOwner,
//	TokenPrimaryGroup,
//	TokenDefaultDacl,
//	TokenSource,
//	TokenType,
//	TokenImpersonationLevel,
//	TokenStatistics,
//	TokenRestrictedSids,
//	TokenSessionId
//};

struct RTL_RESOURCE
{
	CRITICAL_SECTION	CS;
	HANDLE				SharedReleaseSemaphore;
	ULONG				SharedWaiters;
	HANDLE				ExclusiveReleaseSemaphore;
	ULONG				ExclusiveWaiters;
	LONG				NumberActive;
	ULONG_PTR			OwningThreadID;
	ULONG_PTR			Reserved;
	PVOID				DebugInfo;
};

extern "C"
{

NTSYSAPI NTSTATUS NTAPI NtQueryObject(IN HANDLE ObjectHandle, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength OPTIONAL);
NTSYSAPI NTSTATUS NTAPI NtClose(IN HANDLE Handle);
NTSYSAPI NTSTATUS NTAPI NtQuerySecurityObject(IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, OUT SECURITY_DESCRIPTOR_RELATIVE *SecurityDescriptor, IN ULONG Length, OUT ULONG *RequiredLength);
NTSYSAPI NTSTATUS NTAPI NtSetSecurityObject(IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, IN SECURITY_DESCRIPTOR CONST *SecurityDescriptor);

NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT HANDLE *FileHandle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes, OUT IO_STATUS_BLOCK *IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions);
NTSYSAPI NTSTATUS NTAPI NtQueryDirectoryFile(IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PVOID ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT IO_STATUS_BLOCK *IoStatusBlock, OUT PVOID FileInformation, IN ULONG FileInformationLength, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN UNICODE_STRING CONST *FileName OPTIONAL, IN BOOLEAN RestartScan);
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE FileHandle, OUT IO_STATUS_BLOCK *IoStatusBlock, OUT PVOID FileInformation, IN ULONG FileInformationLength, IN FILE_INFORMATION_CLASS FileInformationClass);

NTSYSAPI NTSTATUS NTAPI NtCreateKey(OUT HANDLE *KeyHandle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes, IN ULONG TitleIndex, IN UNICODE_STRING *Class OPTIONAL, IN ULONG CreateOptions, OUT ULONG *Disposition OPTIONAL);
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT HANDLE *KeyHandle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);
NTSYSAPI NTSTATUS NTAPI NtEnumerateKey(IN HANDLE KeyHandle, IN ULONG Index, IN ULONG KeyInformationClass, OUT PVOID KeyInformation, IN ULONG KeyInformationLength, OUT ULONG *ResultLength);
NTSYSAPI NTSTATUS NTAPI NtDeleteKey(IN HANDLE KeyHandle);

NTSYSAPI NTSTATUS NTAPI NtOpenDirectoryObject(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenSymbolicLinkObject(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenSection(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenThread(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes, IN CLIENT_ID *ClientId);

NTSYSAPI NTSTATUS NTAPI NtOpenProcess(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes, IN CLIENT_ID *ClientId);

NTSYSAPI NTSTATUS NTAPI NtOpenJobObject(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenTimer(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenEvent(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenSemaphore(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenMutant(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenIoCompletion(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenEventPair(OUT HANDLE *Handle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes);

NTSYSAPI NTSTATUS NTAPI NtOpenProcessToken(IN HANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, OUT HANDLE *TokenHandle);
NTSYSAPI NTSTATUS NTAPI NtOpenThreadToken(IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, OUT HANDLE *TokenHandle);
NTSYSAPI NTSTATUS NTAPI NtQueryInformationToken(IN HANDLE TokenHandle, IN TOKEN_INFORMATION_CLASS TokenInformationClass, OUT PVOID TokenInformation, IN ULONG TokenInformationLength, OUT ULONG *ReturnLength);

NTSYSAPI ULONG NTAPI RtlNtStatusToDosError(IN NTSTATUS Status);

NTSYSAPI ULONG NTAPI RtlLengthSecurityDescriptor(IN void const *SecurityDescriptor);

NTSYSAPI BOOLEAN NTAPI RtlEqualSid(void const *Sid1, void const *Sid2);

NTSYSAPI VOID NTAPI RtlInitializeResource(RTL_RESOURCE *Resource);
NTSYSAPI VOID NTAPI RtlDeleteResource(RTL_RESOURCE *Resource);
NTSYSAPI BOOLEAN NTAPI RtlAcquireResourceExclusive(RTL_RESOURCE *Resource, BOOLEAN Wait);
NTSYSAPI BOOLEAN NTAPI RtlAcquireResourceShared(RTL_RESOURCE *Resource, BOOLEAN Wait);
NTSYSAPI VOID NTAPI RtlReleaseResource(RTL_RESOURCE *Resource);

}

BOOLEAN IsBogusFilename(UNICODE_STRING *Filename)
{
	switch(Filename->Length)
	{
	case sizeof(WCHAR):
		return Filename->Buffer[0] == L'.';

	case sizeof(WCHAR) * 2:
		return Filename->Buffer[0] == L'.' && Filename->Buffer[1] == L'.';

	default:
		return FALSE;
	}
}

//extern "C" BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(PCWSTR dos_path, PUNICODE_STRING ntpath, PWSTR* file_part, CURDIR* cd);